package com.bcinfo.iccard.service.impl;

import java.sql.Timestamp;
import java.util.List;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import com.bcinfo.iccard.constant.ExpensiveRecordConstant;
import com.bcinfo.iccard.constant.ExportReportConstant;
import com.bcinfo.iccard.constant.MerchantConstant;
import com.bcinfo.iccard.dao.CardSaleTotalMapper;
import com.bcinfo.iccard.dao.ExpenseRecordMapper;
import com.bcinfo.iccard.dao.MerchantMapper;
import com.bcinfo.iccard.dao.MerchantSettlementAmountDetailMapper;
import com.bcinfo.iccard.dao.SettlementExportReportMapper;
import com.bcinfo.iccard.exception.ExpensiveRecordsNotExistException;
import com.bcinfo.iccard.exception.IccardDatabaseException;
import com.bcinfo.iccard.exception.InvalidParametersException;
import com.bcinfo.iccard.exception.MerchantBillingExpenseRecordErrorException;
import com.bcinfo.iccard.exception.MerchantBillingFuncErrorException;
import com.bcinfo.iccard.exception.MerchantIsNotExistException;
import com.bcinfo.iccard.model.CardSaleTotal;
import com.bcinfo.iccard.model.ExpenseRecord;
import com.bcinfo.iccard.model.Merchant;
import com.bcinfo.iccard.model.MerchantSettlementAmountDetail;
import com.bcinfo.iccard.model.SettlementExportReport;
import com.bcinfo.iccard.service.FinancialManageService;
import com.bcinfo.iccard.util.DateUtil;
import com.bcinfo.iccard.util.PaginationList;
import com.bcinfo.iccard.util.TimeUtils;

@Service("financialManageService")
public class FinancialManageServiceImpl implements FinancialManageService
{

    private static final Logger                  _logger = Logger.getLogger(FinancialManageServiceImpl.class);

    private CardSaleTotalMapper                  _cardSaleTotalMapper;

    private MerchantMapper                       _merchantMapper;

    private ExpenseRecordMapper                  _expenseRecordMapper;

    private SettlementExportReportMapper         _settlementExportReportMapper;

    private MerchantSettlementAmountDetailMapper _merchantSettlementAmountDetailMapper;

    public MerchantSettlementAmountDetailMapper get_merchantSettlementAmountDetailMapper()
    {
        return _merchantSettlementAmountDetailMapper;
    }

    public void set_merchantSettlementAmountDetailMapper(
            MerchantSettlementAmountDetailMapper _merchantSettlementAmountDetailMapper)
    {
        this._merchantSettlementAmountDetailMapper = _merchantSettlementAmountDetailMapper;
    }

    public SettlementExportReportMapper get_settlementExportReportMapper()
    {
        return _settlementExportReportMapper;
    }

    public void set_settlementExportReportMapper(SettlementExportReportMapper _settlementExportReportMapper)
    {
        this._settlementExportReportMapper = _settlementExportReportMapper;
    }

    public MerchantMapper get_merchantMapper()
    {
        return _merchantMapper;
    }

    public void set_merchantMapper(MerchantMapper _merchantMapper)
    {
        this._merchantMapper = _merchantMapper;
    }

    public CardSaleTotalMapper get_cardSaleTotalMapper()
    {
        return _cardSaleTotalMapper;
    }

    public void set_cardSaleTotalMapper(CardSaleTotalMapper _cardSaleTotalMapper)
    {
        this._cardSaleTotalMapper = _cardSaleTotalMapper;
    }

    public ExpenseRecordMapper get_expenseRecordMapper()
    {
        return _expenseRecordMapper;
    }

    public void set_expenseRecordMapper(ExpenseRecordMapper _expenseRecordMapper)
    {
        this._expenseRecordMapper = _expenseRecordMapper;
    }

    @Override
    public PaginationList<CardSaleTotal> saleStatistics(String beginTime, String endTime, int pageNo, int pageSize)
            throws IccardDatabaseException, InvalidParametersException
    {

        if (_logger.isDebugEnabled())
        {
            _logger.debug("saleStatistics:beginTime=" + beginTime + ",endTime=" + endTime);
        }

        PaginationList<CardSaleTotal> paginationList = new PaginationList<CardSaleTotal>();
        List<CardSaleTotal> list = null;
        int totalCount = 0;
        try
        {
            totalCount = _cardSaleTotalMapper.selectCountSaleStatistics(beginTime, endTime);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (pageNo <= 0 || totalCount < (pageNo - 1) * pageSize || pageSize <= 0)
        {
            _logger.error("parameter is wrong");
            throw new InvalidParametersException();
        }
        int benginIndex = pageSize * pageNo - pageSize;
        try
        {
            list = _cardSaleTotalMapper.selectSaleStatistics(beginTime, endTime, benginIndex, pageSize);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }

        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
        paginationList.setTotalPage(totalPage);
        paginationList.setCurrPage(pageNo);
        paginationList.setPageSize(pageSize);
        paginationList.setRecords(list);
        paginationList.setTotalRecord(totalCount);
        return paginationList;
    }

    @Override
    public float selectTotalSaleAmount(String beginTime, String endTime)
    {
        float amount = _cardSaleTotalMapper.selectTotalSaleAmount(beginTime, endTime);
        return amount;
    }

    @Override
    public PaginationList<Merchant> findByCodeAndStatus(String merchantCode, Short merchantCheckStatus,
            Short merchantStatus, int pageNo, int pageSize) throws IccardDatabaseException, InvalidParametersException
    {
        if (_logger.isDebugEnabled())
        {
            _logger.debug("findByCodeAndStatus:pageNo=" + pageNo + ",pageSize=" + pageSize);
        }

        PaginationList<Merchant> paginationList = new PaginationList<Merchant>();
        List<Merchant> list = null;
        int totalCount = 0;
        try
        {
            totalCount = _merchantMapper.selectCountByCodeAndStatus(merchantCode, merchantCheckStatus, merchantStatus);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (pageNo <= 0 || totalCount < (pageNo - 1) * pageSize || pageSize <= 0)
        {
            _logger.error("parameter is wrong");
            throw new InvalidParametersException();
        }
        int benginIndex = pageSize * pageNo - pageSize;
        try
        {
            list = _merchantMapper.selectPageByCodeAndStatus(merchantCode, merchantCheckStatus, merchantStatus,
                    benginIndex, pageSize);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }

        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
        paginationList.setTotalPage(totalPage);
        paginationList.setCurrPage(pageNo);
        paginationList.setPageSize(pageSize);
        paginationList.setRecords(list);
        paginationList.setTotalRecord(totalCount);
        return paginationList;
    }

    @Override
    public int updateStatus(Long merchantId, Integer billingStatus) throws IccardDatabaseException,
            MerchantBillingFuncErrorException, MerchantBillingExpenseRecordErrorException
    {
        Merchant merchant = new Merchant();
        merchant.setMerchantId(merchantId);

        int result = 0;
        try
        {
            Merchant _merchant = _merchantMapper.selectByPrimaryKey(merchantId);
            billingStatus = _merchant.getBillingStatus();
            String _encode = _merchant.getMerchantEncode();
            Timestamp _beginTime = _merchant.getBillingUpdateBeginTime();
            Timestamp _endTime = _merchant.getBillingUpdateEndTime();
            Timestamp currentTime = new Timestamp(System.currentTimeMillis());
            int compareResult = 0;
            // 本身暂不结算，那就是说 --用户时点击的 开启结算
            if (billingStatus.intValue() == MerchantConstant.MERCHANT_BILLING_STATUS_0.intValue())
            {
                compareResult = TimeUtils.compareDatesByCompareTo(_beginTime, currentTime);
                if (compareResult == 0)
                {
                    _logger.error("updateStatus:merchantId=" + merchantId + ",billingStatus=" + billingStatus);
                    throw new MerchantBillingFuncErrorException();
                }
                else if (compareResult == 1)
                {
                    merchant.setBillingUpdateEndTime(new Timestamp(System.currentTimeMillis()));
                }
                billingStatus = MerchantConstant.MERCHANT_BILLING_STATUS_1;

            }
            // 本身开启结算，那就是说 --用户时点击的 暂不结算
            else if (billingStatus.intValue() == MerchantConstant.MERCHANT_BILLING_STATUS_1.intValue())
            {

                /*
                 * 根据商家编码和更新开始时间和更新结束时间查询在游客消费记录表 中 未结算的条数
                 * 如果存在的话，不允许进行对商家的 暂不结算 操作
                 * 要先进行报表的导出
                 */
                String _beginT = DateUtil.convertDateToString(_beginTime);
                String _endT = DateUtil.convertDateToString(_endTime);
                int count = _expenseRecordMapper.selectCountByMerchantAndTime(
                        ExpensiveRecordConstant.EXPENSIVERECORD_VALUE_ALL,
                        ExpensiveRecordConstant.EXPENSIVERECORD_ISACCOUNT_ALL,
                        ExpensiveRecordConstant.EXPENSIVERECORD_VALUE_ALL, _encode, _beginT, _endT);
                if (count > 0)
                {
                    _logger.error("updateStatus:selectCountByMerchantAndTime  count > 0");
                    throw new MerchantBillingExpenseRecordErrorException();
                }

                compareResult = TimeUtils.compareDatesByCompareTo(_endTime, currentTime);
                if (compareResult == 0)
                {
                    _logger.error("updateStatus:merchantId=" + merchantId + ",billingStatus=" + billingStatus);
                    throw new MerchantBillingFuncErrorException();
                }
                else if (compareResult == 1)
                {
                    merchant.setBillingUpdateBeginTime(new Timestamp(System.currentTimeMillis()));
                }
                billingStatus = MerchantConstant.MERCHANT_BILLING_STATUS_0;
            }

            merchant.setBillingStatus(billingStatus);
            result = _merchantMapper.updateByPrimaryKeySelective(merchant);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        return result;
    }

    @Override
    public PaginationList<SettlementExportReport> findReportsExportByStatus(Short exportReportStatus, String beginTime,
            String endTime, int pageNo, int pageSize) throws IccardDatabaseException, InvalidParametersException
    {
        if (_logger.isDebugEnabled())
        {
            _logger.debug("findReportsExportByStatus:pageNo=" + pageNo + ",pageSize=" + pageSize);
        }

        PaginationList<SettlementExportReport> paginationList = new PaginationList<SettlementExportReport>();
        List<SettlementExportReport> list = null;
        int totalCount = 0;
        try
        {
            totalCount = _settlementExportReportMapper.selectCountByStatus(exportReportStatus, beginTime, endTime);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (pageNo <= 0 || totalCount < (pageNo - 1) * pageSize || pageSize <= 0)
        {
            _logger.error("parameter is wrong");
            throw new InvalidParametersException();
        }
        int benginIndex = pageSize * pageNo - pageSize;
        try
        {
            list = _settlementExportReportMapper.selectDetailByStatus(exportReportStatus, beginTime, endTime,
                    benginIndex, pageSize);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }

        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
        paginationList.setTotalPage(totalPage);
        paginationList.setCurrPage(pageNo);
        paginationList.setPageSize(pageSize);
        paginationList.setRecords(list);
        paginationList.setTotalRecord(totalCount);
        return paginationList;
    }

    @Override
    public PaginationList<MerchantSettlementAmountDetail> findNotSettleMerchantDetails(Long settlementExportReportId,
            String merchantName, String beginTime, String endTime, int pageNo, int pageSize)
            throws IccardDatabaseException, InvalidParametersException
    {
        if (_logger.isDebugEnabled())
        {
            _logger.debug("findReportsExportByStatus:pageNo=" + pageNo + ",pageSize=" + pageSize);
        }

        PaginationList<MerchantSettlementAmountDetail> paginationList = new PaginationList<MerchantSettlementAmountDetail>();
        List<MerchantSettlementAmountDetail> list = null;
        int totalCount = 0;
        try
        {
            totalCount = _merchantSettlementAmountDetailMapper.selectCountByReportIdAndMerchantName(
                    settlementExportReportId, merchantName, beginTime, endTime);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        if (pageNo <= 0 || totalCount < (pageNo - 1) * pageSize || pageSize <= 0)
        {
            _logger.error("parameter is wrong");
            throw new InvalidParametersException();
        }
        int benginIndex = pageSize * pageNo - pageSize;
        try
        {
            list = _merchantSettlementAmountDetailMapper.selectDetailByReportIdAndMerchantName(
                    settlementExportReportId, merchantName, beginTime, endTime, benginIndex, pageSize);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }

        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
        paginationList.setTotalPage(totalPage);
        paginationList.setCurrPage(pageNo);
        paginationList.setPageSize(pageSize);
        paginationList.setRecords(list);
        paginationList.setTotalRecord(totalCount);
        return paginationList;
    }

    @Override
    public int exportReport(Long settlementExportReportId) throws IccardDatabaseException, MerchantIsNotExistException,
            ExpensiveRecordsNotExistException
    {
        int result = 0;
        List<MerchantSettlementAmountDetail> list = null;
        try
        {

            list = _merchantSettlementAmountDetailMapper.selectDetailByReportIdAndMerchantName(
                    settlementExportReportId, "", "", "", 0, 0);
            Long merchantId = null;
            Timestamp exportReportTime = null;
            for (MerchantSettlementAmountDetail msad : list)
            {

                merchantId = msad.getMerchantId();
                exportReportTime = msad.getExportReportTime();
                Merchant _merchant = _merchantMapper.selectByPrimaryKey(merchantId);
                if (null == _merchant)
                {
                    _logger.error("exportReport:settlementExportReportId=" + settlementExportReportId + ",merchantId="
                            + merchantId + ",merchant is not exist");
                    throw new MerchantIsNotExistException();
                }
                Timestamp _beginTime = _merchant.getBillingUpdateBeginTime();
                Timestamp _endTime = _merchant.getBillingUpdateEndTime();
                String merchantEncode = _merchant.getMerchantEncode();
                int _result = TimeUtils.compareDatesByCompareTo(exportReportTime, _endTime);
                String beginTime = "";
                String endTime = "";
                beginTime = DateUtil.getDate(_beginTime);
                endTime = DateUtil.getDate(_endTime);
                if (_result == 2)
                {
                    beginTime = DateUtil.getDate(exportReportTime);
                    endTime = DateUtil.getDate(exportReportTime);
                }
                List<ExpenseRecord> expenseRecordList = _expenseRecordMapper.selectByMerchantEncodeByDay(
                        merchantEncode, ExpensiveRecordConstant.EXPENSIVERECORD_VALUE_ALL,
                        ExpensiveRecordConstant.EXPENSIVERECORD_ISACCOUNT_NOTSETTLE, beginTime, endTime, 0, 0);
                // if (expenseRecordList == null || expenseRecordList.isEmpty())
                // {
                // _logger.error("exportReport:settlementExportReportId=" + settlementExportReportId
                // + ",expensiverecords  is not exist");
                // throw new ExpensiveRecordsNotExistException();
                // }
                for (ExpenseRecord expenseRecord : expenseRecordList)
                {
                    expenseRecord.setIsAccount(ExpensiveRecordConstant.EXPENSIVERECORD_ISACCOUNT_SETTLE);
                    expenseRecord.setAccountTime(new Timestamp(System.currentTimeMillis()));
                    _expenseRecordMapper.updateByPrimaryKeySelective(expenseRecord);
                }
            }
            // 更新结算导出报表
            SettlementExportReport report = new SettlementExportReport();
            report.setSettlementExportReportId(settlementExportReportId);
            report.setExportReportStatus(ExportReportConstant.EXPORTREPORT_STATUS_1);
            _settlementExportReportMapper.updateByPrimaryKeySelective(report);

            result = 1;
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        return result;
    }

    @Override
    public int exportReportAll() throws IccardDatabaseException, InvalidParametersException,
            MerchantIsNotExistException, ExpensiveRecordsNotExistException
    {
        int result = 0;
        try
        {

            PaginationList<SettlementExportReport> plist = findReportsExportByStatus(
                    ExportReportConstant.EXPORTREPORT_STATUS_0, "", "", 1, 100000);
            List<SettlementExportReport> list = plist.getRecords();
            for (SettlementExportReport settlementExportReport : list)
            {
                Long reportId = settlementExportReport.getSettlementExportReportId();
                try
                {
                    result = exportReport(reportId);

                }
                catch (MerchantIsNotExistException e)
                {
                    _logger.error("exportReportAll:settlementExportReportId=" + reportId + ",merchant is not exist");
                    throw new MerchantIsNotExistException();
                }
                catch (ExpensiveRecordsNotExistException e)
                {
                    _logger.error("exportReportAll:settlementExportReportId=" + reportId
                            + ",expensiverecords  is not exist");
                    throw new ExpensiveRecordsNotExistException();
                }
            }
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }

        return result;
    }

    @Override
    public SettlementExportReport findByReportId(Long reportId) throws IccardDatabaseException
    {
        SettlementExportReport report = null;
        try
        {

            report = _settlementExportReportMapper.selectByPrimaryKey(reportId);
        }
        catch (DataAccessException e)
        {
            _logger.error(ExceptionUtils.getStackTrace(e));
            throw new IccardDatabaseException();
        }
        return report;
    }
}
